package top.yuhaitao.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.commons.collections.MapUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

@SuppressWarnings("deprecation")
public class HttpsUtil {
	public static final int SMALL_TIME = 5000;
	public static final int BIG_TIME = 8000;
	private static final String HTTP = "http";
	private static final String HTTPS = "https";
	private static SSLConnectionSocketFactory sslsf = null;
	private static PoolingHttpClientConnectionManager cm = null;
	private static SSLContextBuilder builder = null;
	static {
		try {
			builder = new SSLContextBuilder();
			// 全部信任,不做身份鉴定.
			builder.loadTrustMaterial(null, new TrustStrategy() {
				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
					return true;
				}
			});
			sslsf = new SSLConnectionSocketFactory(builder.build(), new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
			Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register(HTTP, new PlainConnectionSocketFactory()).register(HTTPS, sslsf).build();
			cm = new PoolingHttpClientConnectionManager(registry);
			cm.setMaxTotal(200);// max connection
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * postKeyValue
	 * 
	 * @param url
	 * @param header
	 * @param param
	 * @return
	 * @throws IOException
	 */
	public static String postKeyValue(String url, Map<String, String> header, Map<String, String> param) throws IOException {
		String result = null;
		CloseableHttpClient httpClient = null;
		HttpPost httpPost = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).setConnectionManagerShared(true).build();
			httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(SMALL_TIME).setConnectTimeout(SMALL_TIME).setSocketTimeout(SMALL_TIME).build();
			httpPost.setConfig(requestConfig);
			// 请求头
			if (MapUtils.isNotEmpty(header)) {
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			// 请求体
			if (MapUtils.isNotEmpty(param)) {
				List<NameValuePair> formparams = new ArrayList<NameValuePair>();
				for (Map.Entry<String, String> entry : param.entrySet()) {
					formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
				httpPost.setEntity(urlEncodedFormEntity);
			}
			httpResponse = httpClient.execute(httpPost);
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				HttpEntity resEntity = httpResponse.getEntity();
				result = EntityUtils.toString(resEntity);
			}
		} finally {
			try {
				if (httpClient != null) {
					httpClient.close();
				}
				if (httpPost != null) {
					httpPost.releaseConnection();
				}
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * postBody
	 * 
	 * @param url
	 * @param header
	 * @param body
	 * @return
	 * @throws IOException
	 */
	public static String postBody(String url, Map<String, String> header, String body) throws IOException {
		String result = null;
		CloseableHttpClient httpClient = null;
		HttpPost httpPost = null;
		CloseableHttpResponse httpResponse = null;
		try {
			httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).setConnectionManagerShared(true).build();
			RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(SMALL_TIME).setConnectTimeout(SMALL_TIME).setSocketTimeout(SMALL_TIME).build();
			httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			// 请求头
			if (MapUtils.isNotEmpty(header)) {
				for (Map.Entry<String, String> entry : header.entrySet()) {
					httpPost.addHeader(entry.getKey(), entry.getValue());
				}
			}
			// 请求体
			httpPost.setEntity(new StringEntity(body, "UTF-8"));
			httpResponse = httpClient.execute(httpPost);
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				HttpEntity resEntity = httpResponse.getEntity();
				result = EntityUtils.toString(resEntity);
			}
		} finally {
			try {
				if (httpClient != null) {
					httpClient.close();
				}
				if (httpPost != null) {
					httpPost.releaseConnection();
				}
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * https get 证书访问
	 * 
	 * @param url
	 * @param p12Path
	 * @param mechId
	 * @throws Exception
	 */
	public static String sslGet(String url, String p12Path, String mechId) throws Exception {
		String result = null;
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File("D:/apiclient_cert.p12"));
		try {
			keyStore.load(instream, mechId.toCharArray());
		} finally {
			if (instream != null) {
				instream.close();
			}
		}
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mechId.toCharArray()).build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

		HttpGet httpGet = null;
		CloseableHttpResponse httpResponse = null;

		try {
			httpGet = new HttpGet(url);
			httpResponse = httpClient.execute(httpGet);
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				HttpEntity resEntity = httpResponse.getEntity();
				result = EntityUtils.toString(resEntity);
			}
		} finally {
			try {
				if (httpClient != null) {
					httpClient.close();
				}
				if (httpGet != null) {
					httpGet.releaseConnection();
				}
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * https post 证书访问
	 * 
	 * @param url
	 * @param p12Path
	 * @param mechId
	 * @throws Exception
	 */
	public static String sslPostBody(String url, String p12Path, String mechId, String body) throws Exception {
		String result = null;
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File("D:/apiclient_cert.p12"));
		try {
			keyStore.load(instream, mechId.toCharArray());
		} finally {
			if (instream != null) {
				instream.close();
			}
		}
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mechId.toCharArray()).build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

		HttpPost httpPost = null;
		CloseableHttpResponse httpResponse = null;

		try {
			httpPost = new HttpPost(url);
			// 请求体
			httpPost.setEntity(new StringEntity(body, "UTF-8"));
			httpResponse = httpClient.execute(httpPost);
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				HttpEntity resEntity = httpResponse.getEntity();
				result = EntityUtils.toString(resEntity);
			}
		} finally {
			try {
				if (httpClient != null) {
					httpClient.close();
				}
				if (httpPost != null) {
					httpPost.releaseConnection();
				}
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	public static void main(String[] args) throws Exception {
		String body = "{\"name\":\"123\"}";
		String postBody1 = HttpUtil.postBody("https://www.yuhaitao.top:443/disburse/remittanceServlet", null, body);
		System.out.println(postBody1);
		String postBody2 = HttpsUtil.postBody("https://www.yuhaitao.top:443/disburse/remittanceServlet", null, body);
		System.out.println(postBody2);
		String postBody3 = HttpUtil.postBody("https://mcar.tpi.cntaiping.com/sso/access/joinup", null, body);
		System.out.println(postBody3);
	}

}